/**
 * @file    get_weather.c
 * @brief   使用心知天气api获取指定城市天气信息
 * @author  zyh <2972140442@qq.com>
 * @date    2025-06-27
 * @license GPL-2.0
 * @note    请先注册心知天气（ 网址：https://www.seniverse.com/ ），
 *          获取密钥，将API_KEY替换为自己的密钥，运行程序后，根据终端
 *          提示输入想要获取信息城市的拼音缩写，输入"exit"退出程序
 */
#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netdb.h>

// 调试用错误输出宏
#define LOG_ERROR(fmt, ...) \
    fprintf(stderr, "[ERROR] %s:%d (%s): " fmt "\n", \
            __FILE__, __LINE__, __func__, ##__VA_ARGS__)

#define SENIVERSE_HOST      "api.seniverse.com"
#define SENIVERSE_PORT      80
#define API_KEY             "*****"
#define REQUEST_BUF_SIZE    1024
#define REV_BUF_SIZE        1024

int main()
{
    // 根据域名获取IP地址
    struct hostent *host;
    host = gethostbyname(SENIVERSE_HOST);
    if ( NULL == host )
    {
        LOG_ERROR("gethostbyname failed,error: %d\n", h_errno);
        exit(EXIT_FAILURE);        
    }
    // 创建套接字(socket)
    int client_fd = socket(AF_INET, SOCK_STREAM, 0);
    if ( -1 == client_fd )
    {
        LOG_ERROR("socket failed,error: %d, %s\n", errno, strerror(errno));
        exit(errno);
    }
  
    // TCP 协议结构体初始化
    struct sockaddr_in server_addr;
    memset( &server_addr, 0, sizeof(server_addr) );
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(SENIVERSE_PORT);
    server_addr.sin_addr = *((struct in_addr *)host->h_addr);

    // 连接服务器(connect)
    if ( -1 == connect(client_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) )
    {
        LOG_ERROR("connect failed,error: %d, %s\n", errno, strerror(errno));
        close(client_fd);
        exit(errno);
    }

    // 收发数据
    char request_buf[REQUEST_BUF_SIZE];
    int bytes_sent;

    char location[50] = {0};
    char api_key[20] = API_KEY;

    char rev_buf[REV_BUF_SIZE];
    int bytes_received;
    int header_end;

    while(1)
    {
        // 获取输入
        printf("请输入要查询地址的拼音缩写：\n");
        scanf("%s",location);
        // 若输入为"exit"，退出
        if ( !strncmp(location, "exit", 4) )
        {
            break;
        }
        // 构造HTTP请求
        memset(request_buf,0,REQUEST_BUF_SIZE);
        snprintf(request_buf, REQUEST_BUF_SIZE,
                "GET /v3/weather/now.json?key=%s&location=%s&language=zh-Hans&unit=c HTTP/1.1\r\n"
                "Host: api.seniverse.com\r\n"
                "\r\n",
                api_key, location);

        // 发送请求
        bytes_sent = send(client_fd, request_buf, strlen(request_buf), 0);
        if (bytes_sent < 0) 
        {
            perror("send failed\n");
            close(client_fd);
            exit(0);
        }
        
        printf("天气数据响应:\n");
        // 接收数据
        bytes_received = recv(client_fd, rev_buf, REV_BUF_SIZE-1, 0);
        if ( bytes_received > 0 )
        {
            rev_buf[bytes_received] = '\0';
            printf("%s", rev_buf);
        }       
        memset(rev_buf,0,REV_BUF_SIZE);
        bytes_received = recv(client_fd, rev_buf, REV_BUF_SIZE-1, 0);
        if ( bytes_received > 0 )
        {
            rev_buf[bytes_received] = '\0';
            printf("%s", rev_buf);
        }  
        printf("\n");

        // 接收错误，退出
        if (bytes_received < 0) 
        {
            LOG_ERROR("recv failed,error: %d, %s\n", errno, strerror(errno));
            close(client_fd);
            exit(errno);
        }

    }
    
    // 关闭连接(close)
    if ( -1 == close(client_fd) )
    {
        LOG_ERROR("semget failed,error: %d, %s\n", errno, strerror(errno));
        exit(errno);
    }


    return 0;
}